  lat, lon = ll.split(',')
    new_location = db.GeoPt(lat, lon)

    # Before changing my timestamp, determine which broadcasts to send.
    broadcasts = Broadcast.getLatestBroadcasts(me.activity_at, new_location, test=(uid in common_uids.values()))
    self.log.debug("Retrieved broadcasts: %r", broadcasts)

    # Update my activity and location.
    me.set_location(new_location)
    me.activity()

    # If censored, tell the user and reset it to false.
    i_was_censored = myMetadata.censored
    if i_was_censored:
      myMetadata.uncensor()

    # Determine the number of profiles to find.
    limit = int( self.request.get('c', 28) )
    if limit > 200 and myMetadata.is_grindrX:
      limit = 200
    elif limit > 100 and (not myMetadata.is_grindrX):
      limit = 100

    self.response.out.write('<?xml version=\"1.0\" encoding=\"UTF-8\"?>')
    self.response.out.write('<grindr>')

    # The login stanza includes most account metadata.
    apns = ''
    if myMetadata.uid in beta_uids:
      apns = '<apns>0</apns>' # Tell the beta testers to unregister.
    if myMetadata.is_grindrX or myMetadata.uid in common_uids.values() or myMetadata.uid in lib.early_push_uids:
      apns = '<apns>1</apns>' # Enable push for the developers.

    login_xml = ''.join([
      '<login>',
        '<imageBaseUrl>%s/getimage?hash=</imageBaseUrl>' % lib.API_BASE,
        '<thumbnailBaseUrl>%s/getthumb?hash=</thumbnailBaseUrl>' % lib.API_BASE,
        '<user>%s</user>' % me.id,
        '<pwd>%s</pwd>' % ('' if myMetadata.password is None else myMetadata.password),
        ('<grindrx_seconds_remaining>%d</grindrx_seconds_remaining>' % myMetadata.grindrx_seconds_remaining) if myMetadata.is_grindrX else '',
        apns,
        '<block_max>30</block_max>' if agent_minor_version() >= 1 else '',
        '<favorite_max>30</favorite_max>' if agent_minor_version() >= 1 else '',
        '<servertime>%s</servertime>' % datetime.utcnow().strftime('%Y%m%dT%H:%M:%S'),
        '<censored>Profile censored</censored>' if i_was_censored else '',
        broadcasts if broadcasts else '',
      '</login>',
    ])
    self.log.debug('Login XML: %s', login_xml)
    self.response.out.write(login_xml)

    # And now for the complete buddy list
    self.response.out.write('<buddylist>')

    # To determine online/offline status of the favorites, check for a ProfileLocation existing for each user.
    self.log.debug('Determining online status of favorites')
    online_keys = set()
    profile_location_keys = [ProfileLocation.key_for_profile_key(x) for x in me.favorite_profile_keys]
    for profile_location_key in Presence.existing_keys(profile_location_keys):
      # This user is online since he has a ProfileLocation on record.
      online_keys.add(profile_location_key.parent())

    count = 0
    for buddyProfile in db_get_iterator(me.favorite_profile_keys, chunk_size=100, return_nones=False):
      online = (buddyProfile.key() in online_keys)
      self.response.out.write(buddyProfile.to_xml(from_buddy=me, favorite=True, online=online))
      count += 1
    self.log.debug('Wrote %d favorites XML', count)

    # XXX: is this necessary?
    del online_keys, profile_location_keys

    self.log.debug("Querying for nearby profiles")
    profiles = me.find_nearby_profiles(limit)
    self.log.debug("Profiles queried")

    me.save(force=True)
    self.log.debug('Profile saved: %r', me)

    self.log.debug('Writing %d found buddy profiles', len(profiles))
    for buddyProfile in profiles:
      self.response.out.write(buddyProfile.to_xml(from_buddy=me, favorite=False, online=True))

    self.log.debug("Users output as xml")
    self.response.out.write('</buddylist>\n')
    self.response.out.write('</grindr>\n')
    self.log.debug('Search complete')